<script lang="ts" setup>
import { reactive, ref, inject } from 'vue'
import { InfoFilled } from '@element-plus/icons-vue'
import { IFileData, IFileItem } from './type'
import type { UploadFile, UploadInstance, UploadRawFile } from 'element-plus'
import { isObject } from '@/utils/is'
import { useMessage } from '@/hooks/web/useMessage'

// inject接收不同的上传api
const uploadApi = inject('uploadApi')

// 父组件传入的值
const props = defineProps({
  // 上传时需携带的参数
  fileParams: {
    type: Object,
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    defualt: () => {}
  },
  sendTip: {
    type: String,
    default: () => ''
  }
})

const emits = defineEmits(['updateList'])

// 弹框信息
const dialogImport = reactive({
  visible: false
})

// 上传文件的列表数据
const importFileData: IFileData = reactive({
  list: []
})

/**
 * 父组件触发弹窗显示
 */
const dialogShow = () => {
  dialogImport.visible = true
}

// 文件组件ref
const uploadRef = ref<UploadInstance>()
// 当前在文件列表的文件
const currentFile = ref<UploadRawFile>()
/**
 * 上传文件进入文件列表
 * @param file 文件信息
 */
const fileChange = (file: UploadFile) => {
  const { name, size, status, raw } = file
  const extension = name.substring(name.lastIndexOf('.') + 1)
  const sizeMB = size && (size / 1024 / 1024).toFixed(2)
  if (!extension.includes('xls')) {
    useMessage().warning({ message: '上传文件只能是 xlsx格式!' })
    return false
  }
  if (Number(sizeMB as string) > 2) {
    useMessage().warning({ message: '上传文件不能超过2MB' })
    return false
  }
  const fileItem: IFileItem = {
    fileName: name,
    fileSize: size as number,
    fileStatus: status
  }
  currentFile.value = raw
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  importFileData.list.push(fileItem)
}

/**
 * 删除列表文件
 */
const handleDelFile = () => {
  importFileData.list = []
  uploadRef.value?.clearFiles()
  currentFile.value = undefined
}

/**
 * 提交文件至服务器
 */
const handleSubmit = async () => {
  if (JSON.stringify(props.fileParams) === '{}') {
    useMessage().warning({ message: props.sendTip })
    return
  } else if (currentFile.value === undefined) {
    useMessage().warning({ message: '请选择需上传的文件' })
    return
  } else {
    const fd = createFormData(currentFile.value as UploadRawFile)
    if (typeof uploadApi === 'function') {
      const res = await uploadApi(fd)
      if (res.data) {
        useMessage().success({ message: '导入成功' })
        emits('updateList')
        close()
      }
    }
  }
}

/**
 * 创建上传参数
 * @params file 文件列表中的file文件
 */
const createFormData = (file: UploadRawFile) => {
  const formData = new FormData()
  formData.append('file', file)
  const params = props.fileParams
  if (isObject(params)) {
    for (const key in params) {
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      formData.append(key, params[key])
    }
  }
  return formData
}

/**
 * 解析文件大小
 * @param data 文件字节数
 */
const filterFileSize = (data: number) => {
  return `${(data / 1024).toFixed(2)}kb` || '--'
}

/**
 * 解析文件状态
 * @param text 状态字段
 */
type textStatus = 'ready' | 'uploading' | 'success' | 'fail'
const filterFileStatus = (text: textStatus) => {
  switch (text) {
    case 'ready':
      return '待上传...'
    case 'uploading':
      return '上传中'
    case 'success':
      return '上传成功'
    case 'fail':
      return '上传失败'
    default:
      break
  }
}

/**
 * 关闭弹窗
 */
const dialogClose = () => {
  dialogImport.visible = false
}

defineExpose({ dialogShow })
</script>

<template>
  <TmeDialog v-model="dialogImport.visible" title="导入" dialogWidth="40%" maxHeight="200px" @close="dialogClose">
    <div>
      <slot />
      <div class="import-tip w-full flex justify-between items-center">
        <div class="import-tip-text flex items-center c-black cursor-default">
          <el-icon>
            <InfoFilled color="#1081E9" />
          </el-icon>
          <span>支持.xls,.xlsx格式，只能单个文件上传，且文件不超过2MB</span>
        </div>
        <el-upload
          ref="uploadRef"
          action=""
          :limit="1"
          :auto-upload="false"
          accept=".xlsx, .xls"
          :show-file-list="false"
          :on-change="fileChange"
        >
          <el-button type="primary">选择文件</el-button>
        </el-upload>
      </div>
      <el-table :data="importFileData.list" border style="width: 100%; margin-top: 8px">
        <el-table-column prop="fileName" label="文件名" align="center" min-width="180" />
        <el-table-column label="文件大小" align="center" min-width="100">
          <template #default="{ row }">{{ filterFileSize(row.fileSize) }}</template>
        </el-table-column>
        <el-table-column label="状态" align="center" min-width="80">
          <template #default="{ row }">{{ filterFileStatus(row.fileStatus) }}</template>
        </el-table-column>
        <el-table-column label="操作" align="center" width="100">
          <el-button type="danger" link @click="handleDelFile">删除</el-button>
        </el-table-column>
      </el-table>
    </div>
    <template #footer>
      <el-button @click="dialogClose">取消</el-button>
      <el-button type="primary" @click="handleSubmit">开始上传</el-button>
    </template>
  </TmeDialog>
</template>

<style lang="scss" scoped>
svg {
  width: 1em;
  height: 1em;
  margin-top: 3px;
}

.import-tip {
  margin-top: 8px;

  .import-tip-text {
    padding: 8px 15px;
    background-color: #e3f4fc;

    span {
      margin-left: 3px;
    }
  }
}
</style>
